package com.yshebkb.sulp.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 *
 * @author yshebkb
 * @date 2018/9/5
 */
@Aspect
@Component
public class LogAspect {

    private Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点
     * 这句话是方法切入点
     * 1 execution (* com.my.blog.website.controller..*.*(..))
     * 2 execution ： 表示执行
     * 3 第一个*号 : 表示返回值类型， *可以是任意类型
     * 4 com.my.blog.website.controller : 代表扫描的包
     * 5 .. : 代表其底下的子包也进行拦截
     * 6 第二个*号 : 代表对哪个类进行拦截，*代表所有类
     * 7 第三个*号 : 代表方法  *代表任意方法
     * 8 (..) : 代表方法的参数有无都可以
     */
    @Pointcut("execution(* com.yshebkb.sulp.controller..*.*(..))")
    public void log() {

    }


    /**
     * 前置通知等可以没有JoinPoint参数
     */
    @Before("log()")
    public void before(JoinPoint joinPoint) throws Throwable {
        ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attrs == null) {
            return;
        }
        HttpServletRequest request = attrs.getRequest();
        logger.info(String.format("URL: %s, IP: %s, HTTP_METHOD: %s, params: %s, args: %s",
                request.getServletPath(), request.getRemoteAddr(),
                request.getMethod(),
                JSON.toJSONString(request.getParameterMap(), SerializerFeature.DisableCircularReferenceDetect),
                JSON.toJSONString(joinPoint.getArgs(), SerializerFeature.DisableCircularReferenceDetect)));
    }

    /**
     * 配置后置返回通知,使用在方法webLog()上注册的切入点
     */
    @AfterReturning(returning = "object", pointcut = "log()")
    public void after(Object object) {
        logger.info("response: " + JSON.toJSONString(object, SerializerFeature.DisableCircularReferenceDetect));
    }
}
